package com.dayu.tcp.protocol.codec;

import com.dayu.tcp.exception.SocketRuntimeException;
import com.dayu.tcp.protocol.K1BaseMessage;
import com.dayu.tcp.protocol.K1MessageStaticFactory;
import com.dayu.tcp.protocol.K1Protocol;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

/**
 * @author yehangtech
 * @date 2025/4/6 16:26
 * @description K1协议解码器
 */
public class K1Decoder extends LengthFieldBasedFrameDecoder {
    /**
     * 最大接收的包大小
     */
    private static final int MAX_FRAME_LENGTH = 20 * 1024 * 1024;//最大20MB

    /**
     * 协议的固定长度
     */
    private static final int HEADER_SIZE = 32;

    public K1Decoder() {
        this(MAX_FRAME_LENGTH, HEADER_SIZE, 4, 0, 0, false);
    }

    public K1Decoder(int maxFrameLength) {
        this(Math.max(maxFrameLength, HEADER_SIZE), HEADER_SIZE, 4, 0, 0, false);
    }

    /**
     * @param maxFrameLength      帧的最大长度
     * @param lengthFieldOffset   length字段偏移的地址
     * @param lengthFieldLength   length字段所占字节长度
     * @param lengthAdjustment    修改帧数据长度字段中定义的值，可以为负数
     * @param initialBytesToStrip 解析时跳过多少字节
     * @param failFast            true-frame长度超过maxFrameLength是抛出TooLongFrameException。false-读完整个帧再抛异常
     */
    public K1Decoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception {
        if (byteBuf == null) {
            return null;
        }
        if (byteBuf.readableBytes() < HEADER_SIZE) {
            throw new SocketRuntimeException("字节数不足");
        }
        //魔术
        final byte[] magic = new byte[K1Protocol.MAGIC.length];
        byteBuf.readBytes(magic);
        //版本
        final int version = byteBuf.readInt();
        //数据包的业务标识
        final int messageType = byteBuf.readInt();
        //sequenceId
        final long sequenceId = byteBuf.readLong();
        //序列化标志
        final byte serializerType = byteBuf.readByte();
        //压缩方式
        final byte compressType = byteBuf.readByte();
        //加密方式
        final byte encryptType = byteBuf.readByte();
        //内存对齐
        final byte[] emptyBytes = new byte[K1Protocol.EMPTY.length];
        byteBuf.readBytes(emptyBytes);
        //内容长度
        final int length = byteBuf.readInt();
        final int readableBytes = byteBuf.readableBytes();
        if (readableBytes != length) {
            throw new SocketRuntimeException("协议中标记的长度不符合实际长度");
        }
        //读取body
        byte[] bodyBytes = new byte[readableBytes];
        byteBuf.readBytes(bodyBytes);

        final K1BaseMessage k1BaseMessage = new K1BaseMessage(magic, version, messageType, sequenceId,
                serializerType, compressType, encryptType, emptyBytes, length, bodyBytes);

        return K1MessageStaticFactory.k1MsgToMsg(k1BaseMessage);
    }
}
